﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;

namespace YArchitech.HVAC
{
	public class GroupPipe<T> where T : MEPCurve
	{
		public GroupPipe(IList<T> pipeList)
		{
			this.WrapPipe(pipeList);
		}

		public bool Execute()
		{
			bool result = false;
			PositivePipe<T> leftPipe = null;
			PositivePipe<T> rightPipe = null;
			try
			{
				this.GetLeftAndRightPipes(ref leftPipe, ref rightPipe);
				this.PutPipesIntoGroups(leftPipe, rightPipe);
				List<PositivePipe<T>> list = new List<PositivePipe<T>>();
				List<PositivePipe<T>> list2 = new List<PositivePipe<T>>();
				foreach (PositivePipe<T> positivePipe in this.pipes)
				{
					if (positivePipe.IsInLeft)
					{
						list.Add(positivePipe);
					}
					if (positivePipe.IsInRight)
					{
						list2.Add(positivePipe);
					}
				}
				List<PositivePipe<T>> list3 = (from a in list
				orderby a.StartPoint.Y
				select a).ToList<PositivePipe<T>>();
				List<PositivePipe<T>> list4 = (from a in list2
				orderby a.EndPoint.X
				select a).ToList<PositivePipe<T>>();
				for (int i = 0; i < list3.Count; i++)
				{
					if (!list3[i].IsGrouped)
					{
						for (int j = 0; j < list4.Count; j++)
						{
							if (!list4[j].IsGrouped && list3[i].GetSystemElementId() == list4[j].GetSystemElementId())
							{
								list3[i].IsGrouped = true;
								this.sortedPipes.Add(new YJKPiping<T>(list3[i].pipe));
								list4[j].IsGrouped = true;
								this.sortedPipes.Add(new YJKPiping<T>(list4[j].pipe));
								break;
							}
						}
					}
				}
				result = true;
			}
			catch (Exception ex)
			{
				ex.ToString();
			}
			return result;
		}

		protected void PutPipesIntoGroups(PositivePipe<T> leftPipe, PositivePipe<T> rightPipe)
		{
			if (leftPipe != null && rightPipe != null)
			{
				XYZ xyz = leftPipe.EndPoint - leftPipe.StartPoint;
				XYZ xyz2 = rightPipe.EndPoint - rightPipe.StartPoint;
				foreach (PositivePipe<T> positivePipe in this.pipes)
				{
					XYZ xyz3 = positivePipe.EndPoint - positivePipe.StartPoint;
					double num = xyz.AngleOnPlaneTo(xyz3, new XYZ(0.0, 0.0, -1.0));
					double num2 = xyz2.AngleOnPlaneTo(xyz3, new XYZ(0.0, 0.0, -1.0));
					num = this.NormalizeAngle(num);
					num2 = this.NormalizeAngle(num2);
					if (PositivePipe<T>.LessThan(num, num2))
					{
						positivePipe.IsInLeft = true;
					}
					else
					{
						positivePipe.IsInRight = true;
					}
				}
			}
		}

		protected double NormalizeAngle(double angle)
		{
			int num = (int)(angle / Math.PI*2);
			double num2 = angle - (double)num * Math.PI*2;
			if (num2 < 0.0)
			{
				num2 += Math.PI*2;
			}
			return num2;
		}

		protected void IntersectWithNormal(Line normalLine, bool isLeftList)
		{
			foreach (PositivePipe<T> positivePipe in this.pipes)
			{
				XYZ xyz = new YJKLine(YJKLineEx.YJKGetBound(positivePipe.StartPoint, positivePipe.EndPoint)).IntersectionPoint(true, normalLine);
				if (xyz != null)
				{
					positivePipe.intersection = xyz;
					if (isLeftList)
					{
						positivePipe.IsInLeft = true;
					}
					else
					{
						positivePipe.IsInRight = true;
					}
				}
			}
		}

		protected bool RemoveDuplicatePipes()
		{
			bool result = false;
			foreach (PositivePipe<T> positivePipe in this.pipes)
			{
				if (positivePipe.IsInLeft && positivePipe.IsInRight)
				{
					double val = positivePipe.intersection.DistanceTo(positivePipe.StartPoint);
					double val2 = positivePipe.intersection.DistanceTo(positivePipe.EndPoint);
					if (PositivePipe<T>.LessThan(val, val2))
					{
						positivePipe.IsInLeft = true;
						positivePipe.IsInRight = false;
					}
					if (PositivePipe<T>.GreaterThan(val, val2))
					{
						positivePipe.IsInLeft = false;
						positivePipe.IsInRight = true;
					}
				}
			}
			return result;
		}

		protected void SortByY(IList<PositivePipe<T>> pipeList)
		{
		}

		protected void WrapPipe(IList<T> pipeList)
		{
			foreach (T wrappedPipe in pipeList)
			{
				PositivePipe<T> item = new PositivePipe<T>(wrappedPipe);
				this.pipes.Add(item);
			}
		}

		protected bool GetLeftAndRightPipes(ref PositivePipe<T> left, ref PositivePipe<T> right)
		{
			bool result = false;
			double num = double.MaxValue;
			double num2 = double.MinValue;
			foreach (PositivePipe<T> positivePipe in this.pipes)
			{
				if (positivePipe.StartPoint.X < num)
				{
					left = positivePipe;
					num = positivePipe.StartPoint.X;
				}
			}
			foreach (PositivePipe<T> positivePipe2 in this.pipes)
			{
				if (!left.Vector.IsParallelTo(positivePipe2.Vector) && positivePipe2.EndPoint.X > num2)
				{
					right = positivePipe2;
					num2 = positivePipe2.EndPoint.X;
				}
			}
			return result;
		}

		public IList<PositivePipe<T>> pipes = new List<PositivePipe<T>>();

		public IList<YJKPiping<T>> sortedPipes = new List<YJKPiping<T>>();
	}
}
